{UTF-8 без BOM}
Unit Buffer;
Interface
Uses routine, List, Process, DispProc;
Const
	MAX_LEN_BUF = high(byte);
Type
	buf_message = string[150];
	PBuffer = ^TBuffer;
	TBuffer = object
		private
			{индекс входящего сообщения}
			index_in:			byte;
			{индекс исходящего сообщения}
			index_out:			byte;
			{возможное количество сообщений}
			len:				byte;
			{текущиее количество сообщений}
			count:				byte;
			{список процессов, ожидающих чтения}
			listWaitRead:	TList;
			{список процессов, ожидающих записи}
			listWaitWrite:	TList;
			buf:				array[0..MAX_LEN_BUF] of buf_message;
		public
			Constructor Init(number_message:byte);
			Destructor	done;
			Function	Read:buf_message;
			Procedure	Write(const m:buf_message);
			Procedure	Wait_Read;
			Procedure	Wait_Write;
			Procedure	Signal_Read;
			Procedure	Signal_Write;
	end;
Implementation
	
	(* TBuffer *)
	(* Constructor *)
	Constructor TBuffer.init;
	begin
		index_in:=0;
		index_out:=0;
		len:=number_message;
		count:=0;
		listWaitRead.init(sizeof(TProcess));
		listWaitWrite.init(sizeof(TProcess));
	end;
	
	(* Destructor *)
	Destructor TBuffer.done;
	begin
		listWaitRead.done;
		listWaitWrite.done;
	end;
	
	(* Wait_Read *)
	Procedure TBuffer.Wait_Read;
	var
		Cur:TProcess;
	begin
		get_current_dispatcher^.get_current_process(cur);
		listWaitRead.push_back(cur);
		get_current_dispatcher^.delayProcess(cur);
		get_current_dispatcher^.activate_next_process;
	end;
	
	(* Wait_Write *)
	Procedure TBuffer.Wait_write;
	var
		cur:TProcess;
	begin
		get_current_dispatcher^.get_current_process(cur);
		listWaitWrite.push_back(cur);
		get_current_dispatcher^.delayProcess(cur);
		get_current_dispatcher^.activate_next_process;
	end;
	
	(* Signal_Read *)
	Procedure TBuffer.Signal_Read;
	var
		cur, local:	TProcess;
	begin
		if (not listWaitRead.empty) then
			begin
				if (listWaitRead.front(local)) then
					begin
						get_current_dispatcher^.get_current_process(cur);
						listWaitRead.pop_front;
						get_current_dispatcher^.resumeProcessNow(local);
						get_current_dispatcher^.activate_next_process;
					end;
			end;
	end;
	
	(* Signal_Write *)
	Procedure TBuffer.Signal_Write;
	var
		cur, local:	TProcess;
	begin
		if (not listWaitWrite.empty) then
			begin
				if (listWaitWrite.front(local)) then
					begin
						get_current_dispatcher^.get_current_process(cur);
						listWaitWrite.pop_front;
						get_current_dispatcher^.resumeProcessNow(local);
						get_current_dispatcher^.activate_next_process;
					end;
			end;
	end;
	
	(* Read *)
	Function	TBuffer.Read;
	var
		m:	buf_message;
	begin
		disable_interrupt;
		if (count = 0) then
			begin
				Wait_Read;
			end;
		dec(count);
		m:=buf[index_out];
		index_out := (index_out + 1) mod len;
		Signal_write;
		Read:=m;
		enable_interrupt;
	end;
	
	(* Write *)
	Procedure	TBuffer.Write;
	begin
		disable_interrupt;
		if (count = len) then
			begin
				Wait_Write;
			end;
		inc(count);
		buf[index_in]:=m;
		index_in := (index_in + 1) mod len;
		Signal_read;
		enable_interrupt;
	end;
begin
end.
